using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using UBlockly.Compotent;
using UBlockly.Graphic;
using UBlockly.Sys;
using UnityEditor;
using UnityEngine;

namespace UBlockly.Scriptable
{
    using System.Text;
    using UBlockly.UI;
    
    public sealed class SerializeTreeNode
    {
        private static int startIndex;
        private string resultCode;
        private string functionName;
        private SerializeTreeNode[] leafTrees;
        private IVarObject defaultParamValue;   //一定只有一个！
        private int leafCount;
        private bool hasDefaultValue;
        public int LeafCount => leafCount;
        public string FunctionName => functionName;
        public string ReturnTypeStr => resultCode;

        private SerializeTreeNode(string function, int leaf)
        {
            leafCount = leaf;
            functionName = function;
            hasDefaultValue = false;
            if (leafCount > 0)
            {
                leafTrees = new SerializeTreeNode[leafCount];
            }
        }
        
        public SerializeTreeNode GetLeaf(int index)
        {
            return leafTrees[index];
        }

        public void AddLeaf(int index, string function, int leaf)
        {
            AddLeaf(index,new SerializeTreeNode(function,leaf));
        }

        public void AddLeaf(int index, SerializeTreeNode tree)
        {
            if(index <0 || index > leafCount-1)
                throw new System.Exception("out of index");
            leafTrees[index] = tree;
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            return Serialiable(this, sb);
        }

        public static SerializeTreeNode FromStr(string str)
        {
            startIndex = 0;
            var tree = Deserialiable(str);
            BlockDescribeData descData;
            if(!BlockGraphic.GetDescribeData(tree.functionName,out descData))
            {
                throw new System.Exception("SerializeTreeNode FromStr(string str) unknow error");
            }
            tree.resultCode = descData.ResultTypeStr;
            return tree;
        }

        public BlockObject CreateDisplayBlock()
        {
            BlockDescribeData data = default;
            Debug.LogError("has defaultValue = "+hasDefaultValue);
            //通过describeData创建node，默认内置函数没有对应block，对应node需要在父node中获取
            if (!BlockGraphic.GetDescribeData(functionName, out data))
                return null;
            var block = BlockGraphic.CreateNode(data,true).Block;
            //内置函数没有对应block
//            if(hasDefaultValue)
//                block.Node.Value.SetParamValue(defaultParamValue);
            if (leafCount > 0)
            {
                for (int i = 0; i < leafCount; i++)
                {
                    var subBlock = GetLeaf(i).CreateDisplayBlock() as PackTypeBlock;
                    if (subBlock == null) //内置函数
                    {
                        if (GetLeaf(i).hasDefaultValue) //对应节点有默认值
                        {
                            block.GetPackerObject().GetParamObject(i).GetCurrentParam().SetParamDisplayValue(GetLeaf(i).defaultParamValue);
                        }

                        continue;
                    }

                    BlockSystem.Pack(subBlock, block.GetPackerObject(), i);
                }
            }

            return block;
        }

        public ILFunc ToRuntimeILFunc()
        {
            ILFunc func = null;//
            if (hasDefaultValue)
            {
                func = new DefaultParamIlFunc(functionName, defaultParamValue.TargetValue);
            }
            else
            {
                func = new BlockILFunc(functionName);
            }
            if (leafCount <= 0) return func;
            func.SetParamCount(leafCount);
            for (int i = 0; i < leafCount; i++)
            {
                func.SetParam(i, GetLeaf(i).ToRuntimeILFunc());
            }

            return func;
        }

        public static SerializeTreeNode SerializeNode(Node root)
        {
            if (root is ComplexNode)
            {
                Debug.LogWarning("ComplexNode cannot turn to a SerializeTreeNode");
                return null;
            }

            SerializeTreeNode rootTree = new SerializeTreeNode(root.Scriptable.GetFunc().FunName,
                (int) root.Scriptable.ParamCount);
            if (root.Scriptable.ParamCount != 0)
            {
                for (int i = 0; i < root.Scriptable.ParamCount; i++)
                {
                    var node = root.Block.GetPackerObject().GetParamObject(i).GetCurrentParam();
                    var subTree = SerializeNode(node);
                    if (subTree.hasDefaultValue = node.IsDefaultParamNode)   //默认参数附值
                    {
                        subTree.defaultParamValue = node.Scriptable.GetDefaultValue();
                    }
                    rootTree.AddLeaf(i,subTree);
                }
            }

            rootTree.resultCode = root.Scriptable.ResultTypeStr;
            return rootTree;
        }

        static SerializeTreeNode Deserialiable(string str)
        {
            var endIndex = str.IndexOf('#', startIndex);
            var sp = str.Substring(startIndex, endIndex - startIndex).Split('-');
            var leafCount = int.Parse(sp[0]);
            var function = sp[1];
            bool hasDefaultValue = leafCount == 0 && function.Contains("@");
            IVarObject defaultObject = null;
            if (hasDefaultValue) //带默认值
            {
                string tempStr = function;
                function = function.Substring(0, function.IndexOf('@'));
                defaultObject = IVarObjectHelper.FromStr(tempStr.Substring(tempStr.IndexOf('@') + 1));
            }
            SerializeTreeNode tree = new SerializeTreeNode(function,leafCount);
            tree.hasDefaultValue = hasDefaultValue;
            if (hasDefaultValue)
            {
                tree.defaultParamValue = defaultObject;
            }

            startIndex = ++endIndex;
            if (leafCount > 0)
            {
                for (int i = 0; i < leafCount;i++)
                {
                    tree.AddLeaf(i, Deserialiable(str));
                }
            }
            return tree;
        } 
        static string Serialiable(SerializeTreeNode tree,StringBuilder sb)
        {
            string functionName = string.IsNullOrEmpty(tree.FunctionName) ? "*":tree.FunctionName;
            var str = $"{tree.LeafCount}-{functionName}#";
            if (tree.LeafCount == 0)
            {
                sb.Append($"{tree.LeafCount}-{functionName}");
                //包含默认参数
                if (tree.hasDefaultValue)
                {
                    sb.Append($"@{IVarObjectHelper.ToStr(tree.defaultParamValue)}");  //默认参数  
                }

                sb.Append("#");
                return sb.ToString();
            }
            sb.Append(str);
            for (int i = 0; i < tree.LeafCount; i++)
            {
                Serialiable(tree.GetLeaf(i), sb);
            }
            return sb.ToString();
        }
    }
}